using Jupiter.Infrastructure.Cache.Interfaces;
using Jupiter.Infrastructure.Domain;
using Jupiter.Infrastructure.Domain.SqlSugar;
using Jupiter.Infrastructure.Domain.SqlSugar.Basic;
using Jupiter.Infrastructure.Exceptions;
using Jupiter.Infrastructure.Permission;
using Jupiter.Infrastructure.Permission.DataPermissions;
using MediatR;
using Microsoft.Extensions.Configuration;
using Wips.AppService.Authorities.Permissions.Requests;
using Wips.Domain.Models.Authorities.Model;

namespace Wips.AppService.SqlSugar.Authorities.Permissions
{
    /// <summary>
    /// 权限请求处理程序
    /// </summary>
    public class PermissionRequestHandler :
        RequestHandlerBase<Permission>,
        IRequestHandler<SavePermissionRequest, bool>,
        IRequestHandler<AddPermissionRequest, bool>
    {
        /// <summary>
        /// 保存权限
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> Handle(SavePermissionRequest request, CancellationToken cancellationToken)
        {
            // 读取角色信息
            var role = await Query<Role>()
                .FirstOrDefaultAsync(p => p.Id == request.RoleId, cancellationToken);
            if (role == null)
            {
                throw new CoreException("找不到角色信息");
            }

            request.MenuIds = request.MenuIds.Distinct().ToList();
            request.OperationIds = request.OperationIds.Distinct().ToList();
            // 更新角色信息
            role.AssignPermissions(UserId);
            // 更新到数据库
            RegisterDirty(role);

            var perId = await Query<RolePermission>()
                .Where(p => p.RoleId == request.RoleId)
                .Select(p => p.PermissionId).Distinct().ToListAsync(cancellationToken);

            //删除权限
            RegisterDeleteRange<Permission>(c => perId.Contains(c.Id!));

            // 删除菜单权限
            RegisterDeleteObjectValueRange<PermissionMenu>(c =>
                perId.Contains(c.PermissionId));

            // 删除操作权限
            RegisterDeleteObjectValueRange<PermissionOperation>(c =>
                perId.Contains(c.PermissionId));

            //
            RegisterDeleteObjectValueRange<RolePermission>(c =>
                c.RoleId == request.RoleId );


            // 权限实体列表
            var permissions = new List<Permission>();
            // 权限菜单实体列表
            var permissionMenus = new List<PermissionMenu>();
            // 权限操作实体列表
            var permissionOperations = new List<PermissionOperation>();
            // 角色权限实体列表
            var rolePermissions = new List<RolePermission>();
            // 处理菜单数据数据
            foreach (var menuId in request.MenuIds)
            {
                var permission = new Permission(AuthoritiePermissionType.Menu);
                // 添加权限
                permissions.Add(permission);
                // 添加权限菜单
                permissionMenus.Add(new PermissionMenu(permission.Id, menuId));
                // 添加角色权限
                rolePermissions.Add(new RolePermission(request.RoleId, permission.Id));
            }

            // 处理操作数据数据
            foreach (var operationId in request.OperationIds)
            {
                var permission = new Permission(AuthoritiePermissionType.Operation);
                // 添加权限
                permissions.Add(permission);
                // 添加操作权限
                permissionOperations.Add(new PermissionOperation(permission.Id, operationId));
                // 添加角色权限
                rolePermissions.Add(new RolePermission(request.RoleId, permission.Id));
            }

            // 保存
            // 权限
            if (permissions.Count > 0)
            {
                await RegisterNewRangeAsync(permissions, cancellationToken: cancellationToken);
            }

            // 菜单权限
            if (permissionMenus.Count > 0)
            {
                await RegisterNewObjectValueRangeAsync(permissionMenus, cancellationToken: cancellationToken);
            }

            // 操作权限
            if (permissionOperations.Count > 0)
            {
                await RegisterNewObjectValueRangeAsync(permissionOperations, cancellationToken: cancellationToken);
            }

            // 角色权限
            if (rolePermissions.Count > 0)
            {
                await RegisterNewObjectValueRangeAsync(rolePermissions, cancellationToken: cancellationToken);
            }

            return true;
        }


        /// <summary>
        /// 添加权限，不带事务性，请在调用方保存
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> Handle(AddPermissionRequest request, CancellationToken cancellationToken)
        {
            var perIds = await Query<RolePermission>()
                .Where(c => c.RoleId == request.RoleId)
                .Select(c => c.PermissionId)
                .Distinct().ToListAsync(cancellationToken);
            //删除权限
            RegisterDeleteRange<Permission>(p => perIds.Contains(p.Id!));

            // 删除菜单权限
            RegisterDeleteObjectValueRange<PermissionMenu>(p =>
                perIds.Contains(p.PermissionId));

            // 删除操作权限
            RegisterDeleteObjectValueRange<PermissionOperation>(p =>
                perIds.Contains(p.PermissionId));

            RegisterDeleteObjectValueRange<RolePermission>(c =>
                c.RoleId == request.RoleId
            );


            // 权限实体列表
            var permissions = new List<Permission>();
            // 权限菜单实体列表
            var permissionMenus = new List<PermissionMenu>();
            // 权限操作实体列表
            var permissionOperations = new List<PermissionOperation>();
            // 角色权限实体列表
            var rolePermissions = new List<RolePermission>();
            // 处理菜单数据数据
            if (request.MenuIds != null)
                foreach (var menuId in request.MenuIds)
                {
                    var permission = new Permission(AuthoritiePermissionType.Menu);
                    // 添加权限
                    permissions.Add(permission);
                    // 添加权限菜单
                    permissionMenus.Add(new PermissionMenu(permission.Id, menuId));
                    // 添加角色权限
                    rolePermissions.Add(new RolePermission(request.RoleId, permission.Id));
                }

            // 处理操作数据数据
            if (request.OperationIds != null)
                foreach (var operationId in request.OperationIds)
                {
                    var permission = new Permission(AuthoritiePermissionType.Operation);
                    // 添加权限
                    permissions.Add(permission);
                    // 添加操作权限
                    permissionOperations.Add(new PermissionOperation(permission.Id, operationId));
                    // 添加角色权限
                    rolePermissions.Add(new RolePermission(request.RoleId, permission.Id));
                }

            // 保存
            // 权限
            if (permissions.Count > 0)
            {
                await RegisterNewRangeAsync(permissions, cancellationToken: cancellationToken);
            }

            // 菜单权限
            if (permissionMenus.Count > 0)
            {
                await RegisterNewObjectValueRangeAsync(permissionMenus, cancellationToken: cancellationToken);
            }

            // 操作权限
            if (permissionOperations.Count > 0)
            {
                await RegisterNewObjectValueRangeAsync(permissionOperations, cancellationToken: cancellationToken);
            }

            // 角色权限
            if (rolePermissions.Count > 0)
            {
                await RegisterNewObjectValueRangeAsync(rolePermissions, cancellationToken: cancellationToken);
            }

            // 提交

            return true;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="securityContextAccessor"></param>
        /// <param name="facadeResolver"></param>
        /// <param name="cacheManager"></param>
        /// <param name="configuration"></param>
        /// <param name="dataPermission"></param>
        public PermissionRequestHandler(ISqlSugarClient dbContext, ISecurityContextAccessor securityContextAccessor,
            IFacadeResolver facadeResolver, ICacheManager cacheManager, IConfiguration configuration,
            IDataPermission dataPermission) : base(
            dbContext, securityContextAccessor, facadeResolver, cacheManager, configuration, dataPermission)
        {
        }
    }
}